/* Includes ------------------------------------------------------------------*/
#include "SystemTick.h"
#include "Led.h"
#include "Button.h"
#include "RF.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define NUMBER_RF_BIT           12          //12 bit 3 trang thai
#define RF_CODE_SIZE            3
#define BUTTON_CODE_SIZE        1
#define TIMEOUT_RF              300         //khoang 300ms
#define TIMEOUT_LEARN_RF        5000        //khoang 5s
#define TIM2_PERIOD             0xFFFF      // reset counter

#define BLOCK_OPERATION    0    /* block 0 in data eeprom memory: address is 0x4000 */

#define ADDRESS_RF1     (FLASH_DATA_START_PHYSICAL_ADDRESS + ((U16)BLOCK_OPERATION * (U16)FLASH_BLOCK_SIZE))
#define ADDRESS_RF2     (ADDRESS_RF1 + RF_CODE_SIZE)
#define ADDRESS_RF3     (ADDRESS_RF2 + RF_CODE_SIZE)
#define ADDRESS_RF4     (ADDRESS_RF3 + RF_CODE_SIZE)
#define ADDRESS_RF5     (ADDRESS_RF4 + RF_CODE_SIZE)
#define ADDRESS_RF6     (ADDRESS_RF5 + RF_CODE_SIZE)

#define ADDRESS_BUTTON1     (ADDRESS_RF6     + BUTTON_CODE_SIZE)
#define ADDRESS_BUTTON2     (ADDRESS_BUTTON1 + BUTTON_CODE_SIZE)
#define ADDRESS_BUTTON3     (ADDRESS_BUTTON2 + BUTTON_CODE_SIZE)
#define ADDRESS_BUTTON4     (ADDRESS_BUTTON3 + BUTTON_CODE_SIZE)
#define ADDRESS_BUTTON5     (ADDRESS_BUTTON4 + BUTTON_CODE_SIZE)
#define ADDRESS_BUTTON6     (ADDRESS_BUTTON5 + BUTTON_CODE_SIZE)

/* Private macro -------------------------------------------------------------*/
#define start_timer()      {TIM2_SetCounter(0); TIM2_Cmd(ENABLE);}
#define reset_timer()      TIM2_SetCounter(0)
#define stop_timer()       TIM2_Cmd(DISABLE)
#define get_timer()        TIM2_GetCounter()

/* Private variables ---------------------------------------------------------*/
__IO BitStatus  v_RfIn;
__IO U16        v_TimeLow = 0;
__IO U16        v_TimeHigh = 0;
__IO bool       v_ReceiveFlag = false;
U8  s_BitCnt;
U8  s_pRFBuff[RF_CODE_SIZE];
U8  s_pRFIncome[RF_CODE_SIZE];
U16 s_RFSysnBitTimeout = 0xFFFF;

U8  s_pCodeButton1[RF_CODE_SIZE];       // = {0x14, 0xDC, 0x0C};
U8  s_pCodeButton2[RF_CODE_SIZE];       // = {0x14, 0xDC, 0x0C};
U8  s_pCodeButton3[RF_CODE_SIZE];       // = {0x14, 0xDC, 0x30};
U8  s_pCodeButton4[RF_CODE_SIZE];       // = {0x14, 0xDC, 0xC0};
U8  s_pCodeButton5[RF_CODE_SIZE];       // = {0x14, 0xDC, 0xC0};
U8  s_pCodeButton6[RF_CODE_SIZE];       // = {0x14, 0xDC, 0xC0};

U8 s_ButtonMapping[TOTAL_BUTTON];

eRfMode s_Mode;
U16     s_TimeoutLearnCnt = 0;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/

/**
  * @brief  External Interrupt PORTD Interrupt routine
  * @param  None
  * @retval None
  */
INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6)
{
    v_RfIn = GPIO_ReadInputPin(RF_PORT, RF_PINS);
    stop_timer();
    if(RESET == v_RfIn)
    {
        v_TimeHigh = get_timer();
    }
    else
    {
        v_TimeLow = get_timer();
        v_ReceiveFlag = true;
    }
    start_timer();
}


  /**
  * @brief  Timer2 Update/Overflow/Break Interrupt routine
  * @param  None
  * @retval None
  */
 INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
{
    /* Cleat Interrupt Pending bit */
    TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
    stop_timer();
}



bool RF_receive( void )
{
    U16 timeHigh;
    U16 timeLow;
    U8 byteIndex;
    U8 temp;

    if(false == v_ReceiveFlag) return (false);
    v_ReceiveFlag = false;

    timeHigh = v_TimeHigh;
    timeLow = v_TimeLow;

    //if ((timeHigh > timeLow*2) && (timeHigh < timeLow*6))
    if (((timeHigh>>1) > timeLow) && ((timeHigh>>3) < timeLow))
    {
        byteIndex = (s_BitCnt>>3) & 0x03;
        temp = s_pRFBuff[byteIndex]<<1;
        s_pRFBuff[byteIndex] = temp | 1;
    }
    //else if ((timeLow > timeHigh*2) && (timeLow < timeHigh*6))
    else if (((timeLow >>1) > timeHigh) && ((timeLow>>3) < timeHigh))
    {
        byteIndex = (s_BitCnt>>3) & 0x03;
        temp = s_pRFBuff[byteIndex]<<1;
        s_pRFBuff[byteIndex] = temp;
    }
    else
    {
        s_BitCnt = 0;
        return (false);
    }

    s_BitCnt++;
    if ((NUMBER_RF_BIT*2) <= s_BitCnt)
    {
        stop_timer();
        s_pRFIncome[0] = s_pRFBuff[0];
        s_pRFIncome[1] = s_pRFBuff[1];
        s_pRFIncome[2] = s_pRFBuff[2];
        s_BitCnt = 0;
        if(s_RFSysnBitTimeout > TIMEOUT_RF)
        {
            s_RFSysnBitTimeout = 0;
            return (true);
        }
        s_RFSysnBitTimeout = 0;
    }

    return (false);
}


void Rf_TimerInterrupt(void)
{
    if( 0xFFF0 > s_RFSysnBitTimeout ) ++s_RFSysnBitTimeout;
    if( 0xFFFF > s_TimeoutLearnCnt ) ++s_TimeoutLearnCnt;
}


void Rf_Init(void)
{
    U32 addr;
    // Initialize I/Os in Input Mode and external interrupt
    GPIO_Init(RF_PORT, RF_PINS, GPIO_MODE_IN_PU_IT);
    EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_RISE_FALL);

    /* Define flash programming Time*/
    FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);
    FLASH_Unlock(FLASH_MEMTYPE_PROG);
    /* Wait until Flash Program area unlocked flag is set*/
    while (FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);
    /* Unlock flash data eeprom memory */
    FLASH_Unlock(FLASH_MEMTYPE_DATA);
    /* Wait until Data EEPROM area unlocked flag is set*/
    while (FLASH_GetFlagStatus(FLASH_FLAG_DUL) == RESET);

    addr = ADDRESS_RF1;
    s_pCodeButton1[0] = FLASH_ReadByte(addr++);
    s_pCodeButton1[1] = FLASH_ReadByte(addr++);
    s_pCodeButton1[2] = FLASH_ReadByte(addr);
    addr = ADDRESS_RF2;
    s_pCodeButton2[0] = FLASH_ReadByte(addr++);
    s_pCodeButton2[1] = FLASH_ReadByte(addr++);
    s_pCodeButton2[2] = FLASH_ReadByte(addr);
    addr = ADDRESS_RF3;
    s_pCodeButton3[0] = FLASH_ReadByte(addr++);
    s_pCodeButton3[1] = FLASH_ReadByte(addr++);
    s_pCodeButton3[2] = FLASH_ReadByte(addr);
    addr = ADDRESS_RF4;
    s_pCodeButton4[0] = FLASH_ReadByte(addr++);
    s_pCodeButton4[1] = FLASH_ReadByte(addr++);
    s_pCodeButton4[2] = FLASH_ReadByte(addr);
    addr = ADDRESS_RF5;
    s_pCodeButton5[0] = FLASH_ReadByte(addr++);
    s_pCodeButton5[1] = FLASH_ReadByte(addr++);
    s_pCodeButton5[2] = FLASH_ReadByte(addr);
    addr = ADDRESS_RF6;
    s_pCodeButton6[0] = FLASH_ReadByte(addr++);
    s_pCodeButton6[1] = FLASH_ReadByte(addr++);
    s_pCodeButton6[2] = FLASH_ReadByte(addr);

    addr = ADDRESS_BUTTON1;
    s_ButtonMapping[0] = FLASH_ReadByte(addr++);
    s_ButtonMapping[1] = FLASH_ReadByte(addr++);
    s_ButtonMapping[2] = FLASH_ReadByte(addr++);
    s_ButtonMapping[3] = FLASH_ReadByte(addr++);
    s_ButtonMapping[4] = FLASH_ReadByte(addr++);
    s_ButtonMapping[5] = FLASH_ReadByte(addr);

    /* Time base configuration */
    TIM2_TimeBaseInit(TIM2_PRESCALER_16, TIM2_PERIOD);
    /* Clear TIM2 update flag */
    TIM2_ClearFlag(TIM2_FLAG_UPDATE);
    /* Enable update interrupt */
    TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);

    SysTick_Registration(&Rf_TimerInterrupt);

    v_RfIn = RESET;
    s_Mode = NORMAL;
}


void Rf_StoreCode( U32 iAddr, U8* iData )
{
    iData[0] = s_pRFIncome[0];
    iData[1] = s_pRFIncome[1];
    iData[2] = s_pRFIncome[2];

    FLASH_ProgramByte( iAddr++, iData[0] );
    FLASH_ProgramByte( iAddr++, iData[1] );
    FLASH_ProgramByte( iAddr, iData[2] );
}


eRfMode Rf_GetMode( void )
{
    return (s_Mode);
}


void Rf_SetMode( eRfMode iMode )
{
    s_Mode = iMode;
    s_TimeoutLearnCnt = 0;
}


void Rf_RunOne(void)
{
    switch( s_Mode )
    {
    default:
    case NORMAL:
        {
            if( true == RF_receive() && (NORMAL_BUTTON == Button_GetMode()) )
            {
                if( s_pCodeButton1[0] == s_pRFIncome[0] && s_pCodeButton1[1] == s_pRFIncome[1] && s_pCodeButton1[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY1 );
                }

                else if( s_pCodeButton2[0] == s_pRFIncome[0] && s_pCodeButton2[1] == s_pRFIncome[1] && s_pCodeButton2[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY2 );
                }

                else if( s_pCodeButton3[0] == s_pRFIncome[0] && s_pCodeButton3[1] == s_pRFIncome[1] && s_pCodeButton3[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY3 );
                }

                else if( s_pCodeButton4[0] == s_pRFIncome[0] && s_pCodeButton4[1] == s_pRFIncome[1] && s_pCodeButton4[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY4 );
                }

                else if( s_pCodeButton5[0] == s_pRFIncome[0] && s_pCodeButton5[1] == s_pRFIncome[1] && s_pCodeButton5[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY5 );
                }

                else if( s_pCodeButton6[0] == s_pRFIncome[0] && s_pCodeButton6[1] == s_pRFIncome[1] && s_pCodeButton6[2] == s_pRFIncome[2] )
                {
                    Led_InvOutput( RELAY6 );
                }
            }
        } break;

    case ENTER_LEARN_RF:
        {
            Led_SetAllOutput(false);
            Led_SetOutput( RELAY1, true );
            Rf_SetMode( LEARN_RF_FOR_RELAY1 );
        } break;

    case LEARN_RF_FOR_RELAY1:
        {
            if( true == RF_receive() )
            {
                Rf_StoreCode( ADDRESS_RF1, s_pCodeButton1 );
                Rf_SetMode( LEARN_RF_FOR_RELAY2 );
                Led_SetOutput( RELAY1, false );
                Led_SetOutput( RELAY2, true );
            }
            if( TIMEOUT_LEARN_RF <= s_TimeoutLearnCnt )
            {
                Rf_SetMode( QUIT_LEARN_RF );
            }
        } break;

    case LEARN_RF_FOR_RELAY2:
        {
            if( true == RF_receive() )
            {
                Rf_StoreCode( ADDRESS_RF2, s_pCodeButton2 );
                Rf_SetMode( LEARN_RF_FOR_RELAY3 );
                Led_SetOutput( RELAY2, false );
                Led_SetOutput( RELAY3, true );
            }
            if( TIMEOUT_LEARN_RF <= s_TimeoutLearnCnt )
            {
                Rf_SetMode( QUIT_LEARN_RF );
            }
        } break;

    case LEARN_RF_FOR_RELAY3:
        {
            if( true == RF_receive() )
            {
                Rf_StoreCode( ADDRESS_RF3, s_pCodeButton3 );
                Rf_SetMode( LEARN_RF_FOR_RELAY4 );
                Led_SetOutput( RELAY3, false );
                Led_SetOutput( RELAY4, true );
            }
            if( TIMEOUT_LEARN_RF <= s_TimeoutLearnCnt )
            {
                Rf_SetMode( QUIT_LEARN_RF );
            }
        } break;

    case LEARN_RF_FOR_RELAY4:
        {
            if( true == RF_receive() )
            {
                Rf_StoreCode( ADDRESS_RF4, s_pCodeButton4 );
                Rf_SetMode( LEARN_RF_FOR_RELAY5 );
                Led_SetOutput( RELAY4, false );
                Led_SetOutput( RELAY5, true );
            }
            if( TIMEOUT_LEARN_RF <= s_TimeoutLearnCnt )
            {
                Rf_SetMode( QUIT_LEARN_RF );
            }
        } break;

    case LEARN_RF_FOR_RELAY5:
        {
            if( true == RF_receive() )
            {
                Rf_StoreCode( ADDRESS_RF5, s_pCodeButton5 );
                Rf_SetMode( QUIT_LEARN_RF );
                Led_SetOutput( RELAY5, false );
            }
            if( TIMEOUT_LEARN_RF <= s_TimeoutLearnCnt )
            {
                Rf_SetMode( QUIT_LEARN_RF );
            }
        } break;

    case QUIT_LEARN_RF:
        {
            Led_SetAllOutput(false);
            Rf_SetMode( NORMAL );
        } break;

    }
}

void Rf_SaveButtonMapping(void)
{
    U8 i;
    U32 addr = ADDRESS_BUTTON1;

    for (i=0; i<TOTAL_BUTTON; ++i)
    {
        FLASH_ProgramByte( addr++, s_ButtonMapping[i] );
    }
}
